// reduce() 按顺序对数组的每个元素执行用户提供的“reducer”回调函数，传入前一个元素计算的返回值
/*
    语法：reduce(callbackFn, initialValue)
*/


// const array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

// array.reduce((prev, cur, index, array) => {
//     console.log(prev, cur, index, array)
// }, 0);

/*
    fn ： callback 必选 
       接受4个参数 Accumulator (acc) (累计器)、Current Value (cur) (当前值)、Current Index (idx) (当前索引)、Source Array (src) (源数组)
    initialValue ： 初始值 可选
*/

/*
    注意点：
        1、callback(...)一般需要返回值
        2、不会改变原数组


    实现思路：
        1、先获取初始累计的值（分成两种情况：有提供initialValue || 未提供initialValue）
        2、遍历数组并执行callback(...)
        3、返回累计值
*/
Array.prototype.myReduce = function(fn, initialValue) {
    //---------------------------------------------------各种检验---------------------------------------------------------------
    // （1）数组的有效性
    if (this === null) {
        throw new TypeError('Array.prototype.reduce called on null or undefined');
    };

    // （2）回调函数
    if (typeof fn !== 'function') {
        throw new TypeError(fn + ' is not a function');
    };

    const obj = Object(this);   
    const lenValue = obj.length;
    // >>>无符号移位：该操作符会将第一个操作数向右移动指定的位数
    // 向右被移出的位被丢弃，左侧用0填充
    // x >>> 0本质上就是保证x有意义（为数字类型），且为正整数，在有效的数组范围内（0 ～ 0xFFFFFFFF），且在无意义的情况下缺省值为0
    const len = lenValue >>> 0;

    if (len === 0 && !initialValue) {
        throw new TypeError('the array contains no elements and initialValue is not provied.');
    };

    
    //----------------------------------------------获取accumulator--------------------------------------------------------------
    let k = 0;
    let accumulator;
    /*
        分成两种情况来获取accumulator  【累加器】
        （1）存在initialValue: accumulator = initialValue;
        （2）不存在initialValue: accumulator = 数组的第一个有效元素 
    */ 

    if (initialValue) {
        accumulator = initialValue;
    } else {
        // 获取数组的第一个有效元素 
        let kPresent = false;
        while (!kPresent && k < len) {
            const pK = String(k);
            kPresent = obj.hasOwnProperty(pK);
            if (kPresent) {
                accumulator = obj[pK];
            };
            k++
        };

        if (!kPresent) {
            throw new TypeError('the array contains error elements');
        };
    };
    //----------------------------------------------循环递归--------------------------------------------------------------
    // 当accumulator = initialValue时 k=0
    // 当accumulator = 数组的第一个有效元素 k=1
    while (k < len) {
        if (k in obj) {
            // callback一般需要返回值
            // obj[k] 就是当前元素 k就是index
            accumulator = fn(accumulator, obj[k], k, obj);
        };
        k++;
    };
    return accumulator;
};


// test
const array = [2,3,4,5,6,7,8,9,10,11];

let res = array.myReduce((prev, cur) => {
    // console.log(prev);
    return prev + cur;
});

console.log(res);   // 65
